﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace mrp16062010
{
    class CizelgeIsMerkezi
    {
        public string Id { get; set; }
        public IsMerkezi Merkez;
        public List<IsParcasi> IsListe = new List<IsParcasi>();
        //public List<IsParcasi> KontrolEdilecek = new List<IsParcasi>();
        public List<IsParcasi> KontrolEdildi = new List<IsParcasi>();

        private bool test;

        public bool Test
        {
            get { return test; }
            set { test = value; }
        }
        

        private void IsListeEkle(IsParcasi gelen)
        {
            //IsListe.Add(gelen);
            ((List<IsParcasi>)IsListe).Add(gelen);
            //KontrolEdilecek.Clear();
            //KontrolEdilecek.AddRange(IsListe);
        }

        /*private void KontroluTemizle()
        {
           // KontrolEdilecek.Clear();
            //KontrolEdilecek.AddRange(IsListe);
        }*/
        /*TODO geri yüklemede datetime.now dan küçükse eğer yükleme işlemini ileri yükleme 
         * olarak değiştirecez ancak bunu yapabilmek için bizim ibr event fırlatmamız lazım ve
         * bu eventin Cizelge classı tarafından yakalanıp eklenen iş parçacıklarının geri 
         * alınması gerekir. Geri alındıktan sonra da ileri yükleme gerçekleştirilir.*/
        List<IsParcasi> kontrolEdilen = new List<IsParcasi>();
        public void GeriYukle(IsParcasi gelenIP)
        {
            geriYukle(gelenIP, 0);
            //KontroluTemizle();
        }

        //burada iş parçalarını ekliyoruz
        private void geriYukle(IsParcasi gelenIP, int derinlik)
        {
            bool tatilMi;
            //Stopwatch sw = new Stopwatch();
            //sw.Start();
            IsParcasi kesisenParca = Kontrol(gelenIP, false, out tatilMi);
            //sw.Stop();
            //string ExecutionTimeTaken = string.Format("Minutes :{0}\nSeconds :{1}\n Mili seconds :{2}", sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.TotalMilliseconds);
            //Console.Out.WriteLine(ExecutionTimeTaken);
            if (kesisenParca == null)
            {
                
                IsListe.Add(gelenIP);
                //IsListe = IsListe.OrderBy(x => x.BasTarihi).ToList();

            }
            else
            {
                //Eğer kesiştiyse

                if (tatilMi)
                {
                    gelenIP.Uzat(-(kesisenParca.BitTarihi - kesisenParca.BasTarihi));
                    KontrolEdildi.Add(kesisenParca);
                    geriYukle(gelenIP, derinlik + 1);
                }
                else
                {
                    //Eğer uzadıysa ve tatil değilse kesişen
                    if (gelenIP.UzadiMi)
                    {
                        gelenIP.UzatmayiGeriAl();
                        KontrolEdildi.Clear();
                        //KontroluTemizle();
                    }
                    gelenIP.GeriHesapla(kesisenParca.BasTarihi);
                    geriYukle(gelenIP, derinlik + 1);
                }
            }
            KontrolEdildi.Clear();
           
            /*
            bool tatilMi;



            IsParcasi kesisenParca = Kontrol(gelenIP, false, out tatilMi);
            
            if (kesisenParca == null)
            {
                IsListe.Add(gelenIP);
                IsListe = (from x in IsListe
                           orderby x.BasTarihi
                           select x).ToList<IsParcasi>();

            }
            else
            {
                //Eğer kesiştiyse
                if (tatilMi)
                {
                    bool uzatmaSonucu = gelenIP.Uzat(-(kesisenParca.BitTarihi - kesisenParca.BasTarihi));
                    if (!uzatmaSonucu)
                    {
                        
                    }
                    else
                    {
                        geriYukle(gelenIP);
                    }
                    
                }
                else
                {
                    //Eğer uzadıysa ve tatil değilse kesişen
                    if (gelenIP.UzadiMi)
                    {
                        gelenIP.UzatmayiGeriAl();
                        //KontroluTemizle();
                    }
                    gelenIP.GeriHesapla(kesisenParca.BasTarihi);
                    geriYukle(gelenIP);
                }
            }*/
        }

        public void IleriYukle(IsParcasi gelenIP, int derinlik)
        {
            /*if (derinlik>60)
            {
                
            }*/
            bool tatilMi;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            IsParcasi kesisenParca = Kontrol(gelenIP, true, out tatilMi);
            sw.Stop();
            string ExecutionTimeTaken = string.Format("Minutes :{0}\nSeconds :{1}\n Mili seconds :{2}", sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.TotalMilliseconds);
            //Console.Out.WriteLine(ExecutionTimeTaken);
            if (kesisenParca == null)
            {
                IsListe.Add(gelenIP);
                IsListe = IsListe.OrderBy(x => x.BasTarihi).ToList();

                //IsListe.Add(gelenIP);
                //IsListe = (from x in IsListe
                //           orderby x.BasTarihi
                //           select x).ToList<IsParcasi>();

            }
            else
            {
                //Eğer kesiştiyse

                if (tatilMi)
                {
                    gelenIP.Uzat((kesisenParca.BitTarihi - kesisenParca.BasTarihi));
                    KontrolEdildi.Add(kesisenParca);
                    IleriYukle(gelenIP, derinlik+1);
                }
                else
                {
                    //Eğer uzadıysa ve tatil değilse kesişen
                    if (gelenIP.UzadiMi)
                    {
                        gelenIP.UzatmayiGeriAl();
                        KontrolEdildi.Clear();
                        //KontroluTemizle();
                    }
                    gelenIP.IleriHesapla(kesisenParca.BitTarihi);
                    IleriYukle(gelenIP, derinlik + 1);
                }
            }
            KontrolEdildi.Clear();
        
        }
        //İleri ise 1 geri ise 0
        public IsParcasi Kontrol(IsParcasi gelenIP, bool yuklemeTipi, out bool tatilMi)
        {
            if (test)
            {
                tatilMi = false;
                return null;
            }
            IsParcasi KesisenParca = null;
            tatilMi = false;
           
            var liste = (from x in IsListe.Except(KontrolEdildi)
                                     where (!((x.BasTarihi < gelenIP.BasTarihi && x.BitTarihi < gelenIP.BasTarihi) || (x.BasTarihi > gelenIP.BitTarihi && x.BitTarihi > gelenIP.BitTarihi)))
                                    select x);
            if (liste.FirstOrDefault()==null)
            {
                return null;
            }

            for (int say = 0; say < liste.Count(); say++)
            {
                IsParcasi item = liste.ElementAt(say);
                Kesisim? sonuc = IsKesisim(gelenIP, item);
                if (sonuc.HasValue)
                {
                    if (item.TatilMi)
                    {
                        //Tatille çakışıyorsa

                        if (yuklemeTipi == true)//IlerI yukleme Ise
                        {
                            if (sonuc.Value == Kesisim.Esit || sonuc.Value == Kesisim.SolEsSagDis || sonuc.Value == Kesisim.SolEsSagIc
                            || sonuc.Value == Kesisim.SolIcSagDis || sonuc.Value == Kesisim.SolIcSagEs || sonuc.Value == Kesisim.SolIcSagIc
                            )
                            {
                                //Tatili geçmeli, atlamalı yani tatilin bitiş zamanında başlamalı
                                tatilMi = false;
                                return item;
                            }
                            else
                            {
                                //Tatil boyunca uzatmalı
                                tatilMi = true;
                                return item;
                            }
                        }
                        else //GerI yukleme Ise
                        {
                            if (sonuc.Value == Kesisim.Esit || sonuc.Value == Kesisim.SolDisSagIc || sonuc.Value == Kesisim.SolIcSagIc
                                                       || sonuc.Value == Kesisim.SolEsSagIc || sonuc.Value == Kesisim.SolIcSagEs || sonuc.Value == Kesisim.SolDisSagEs
                                                       )
                            {
                                //Tatili geçmeli, atlamalı yani tatilin bitiş zamanında başlamalı
                                tatilMi = false;
                                return item;
                            }
                            else
                            {
                                //Tatil boyunca uzatmalı
                                tatilMi = true;
                                return item;
                            }
                        }


                    }
                    else
                    {
                        //Tatille çakışmıyorsa
                        tatilMi = false;
                        return item;
                    }
                    break;
                }
            }
            return KesisenParca;
            /*
            if (gelenIP.Op.Ad == "Montaj 4")
            {

            }
            //Eğer herhangi bir iş parçası kesişiyorsa kesişen parçayı döndürür
            IsParcasi KesisenParca = null;
            tatilMi = false;
            //Listeyi tarihlere göre sıralayalım, kontrol edilen tatilleri almayalım.
            
            List<IsParcasi> liste = (from x in KontrolEdilecek
                                     where (!((x.BasTarihi < gelenIP.BasTarihi && x.BitTarihi < gelenIP.BasTarihi) && (x.BasTarihi > gelenIP.BitTarihi && x.BitTarihi > gelenIP.BitTarihi)))
                                     orderby x.BasTarihi
                                     select x).ToList<IsParcasi>();
            foreach (IsParcasi item in liste)
            {
                
                
                //Tatil zamanlarını kontrol ediyoruz varsa gelen parçayı geçici olarak tatil boyunca genişletiyoruz.
                Kesisim? sonuc;
                try
                {
                    sonuc= IsKesisim(gelenIP, item);
                }
                catch (Exception)
                {
                    
                    throw;
                }
                
                if (sonuc.HasValue)
                {
                    if (item.TatilMi)
                    {
                        tatilMi = true;
                        if (yuklemeTipi)
                        {
                            //İleri yüklemede
                            if (sonuc.Value == Kesisim.SolDisSagDis || sonuc.Value == Kesisim.SolDisSagEs || sonuc.Value == Kesisim.SolDisSagIc)
                            {
                                KontrolEdilecek.Remove(item);
                            }
                            else
                            {
                                //Tatil değilmiş gibi davransın çünkü tatillin içinde çakışıyor
                                tatilMi = false;
                            }
                        }
                        else
                        {
                            //Geri yüklemede
                            if (sonuc.Value == Kesisim.SolDisSagDis || sonuc.Value == Kesisim.SolEsSagDis || sonuc.Value == Kesisim.SolIcSagDis)
                            {
                                KontrolEdilecek.Remove(item);
                                //kontrolEdilen.Add(item);
                            }
                            else
                            {
                                tatilMi = false;
                            }
                        }
                    }
                    KesisenParca = item;
                    break;
                }
            }

            return KesisenParca;
            */
        }

        private Kesisim? IsKesisim(IsParcasi gelenIP, IsParcasi item)
        {

            //Başlama ve bitiş tarihlerinin eşit olması
            bool a1 = gelenIP.BasTarihi == item.BasTarihi && gelenIP.BitTarihi == item.BitTarihi;
            //Var olan iş parçasından sonra başlayıp sonra biten ve kesişen (bir kısmı kesişen)
            bool a2 = gelenIP.BasTarihi > item.BasTarihi && item.BitTarihi < gelenIP.BitTarihi && gelenIP.BasTarihi < item.BitTarihi;
            //Var olan iş parçasından önce başlayıp önce biten ve kesişen (bir kısmı kesişen)
            bool a3 = gelenIP.BasTarihi < item.BasTarihi && gelenIP.BitTarihi < item.BitTarihi && gelenIP.BitTarihi > item.BasTarihi;
            //Var olan iş parçası eklenecek olandan küçük ve  çakışıyor (gelen büyük ve çakışıyor)
            bool a4 = gelenIP.BasTarihi < item.BasTarihi && gelenIP.BitTarihi > item.BitTarihi;
            //Var olan iş parçası eklenecek olandan büyükse ve kesişiyorsa (varolanın içinde kesişiyor)
            bool a5 = gelenIP.BasTarihi > item.BasTarihi && gelenIP.BitTarihi < item.BitTarihi;
            //Gelen iş parçasının başlama zamanı var olan ile aynı, bitiş zamanı küçük
            bool a6 = gelenIP.BasTarihi == item.BasTarihi && gelenIP.BitTarihi < item.BitTarihi;
            //Gelen iş parçasının bitiş zamanı var olan ile aynı, başlama zamanı büyük
            bool a7 = gelenIP.BasTarihi > item.BasTarihi && gelenIP.BitTarihi == item.BitTarihi;
            //Gelen iş parçasının başlangıç tarihi küçük bitiş tarihi eşitse
            bool a8 = gelenIP.BasTarihi < item.BasTarihi && gelenIP.BitTarihi == item.BitTarihi;
            //Gelen iş parçasının başlangıç tarihi eşit, bitiş tarihi büyükse;
            bool a9 = gelenIP.BasTarihi == item.BasTarihi && gelenIP.BitTarihi > item.BitTarihi;

            if (a1)
            {
                return Kesisim.Esit;
            }
            else if (a2)
            {
                return Kesisim.SolIcSagDis;
            }
            else if (a3)
            {
                return Kesisim.SolDisSagIc;
            }
            else if (a4)
            {
                return Kesisim.SolDisSagDis;
            }
            else if (a5)
            {
                return Kesisim.SolIcSagIc;
            }
            else if (a6)
            {
                return Kesisim.SolEsSagIc;
            }
            else if (a7)
            {
                return Kesisim.SolIcSagEs;
            }
            else if (a8)
            {
                return Kesisim.SolDisSagEs;
            }
            else if (a9)
            {
                return Kesisim.SolEsSagDis;
            }
            return null;
        }

        public enum Kesisim
        {
            Esit=0,
            SolIcSagDis=1,
            SolDisSagIc=2,
            SolDisSagDis=3,
            SolIcSagIc=4,
            SolEsSagIc=5,
            SolIcSagEs=6,
            SolDisSagEs=7,
            SolEsSagDis=8
        }
    }
}